fs = require("fs");
ug = require("./uglify-js").uglify;
parser = require("./uglify-js").parser;

tree = require("./treehugger/tree");
traverse = require("./treehugger/traverse");
treehuggerParser = require("./treehugger/js/parse");
scriptbuilder = require("./scriptbuilder");
visitor = require("./visitor");	

// My compiler uses a modified version of uglify-js that feeds batch statements into a code splitter based on treehugger.
compile = function(source) {
	var code = ug.gen_code(parser.parse(source), {beautify:true});

	var batches = ug.batches;
	for(name in batches) {
		var batch = batches[name];

	    // Parse the AST tree using uglify
	    ast = treehuggerParser.parse(batch.code);
	    traverse.addParentPointers(ast);

	    // Process the batch block
		code = code.replace('{'+name+'}', processBatch(ast[0]));
	}

	return code;
}

getAST = function(source) {
    var batches = ug.batches;
    var str = "";

    for(name in batches) {
        var batch = batches[name];

        // Parse the AST tree using uglify
        ast = treehuggerParser.parse(batch.code);
        str = str + ast.toPrettyString() + "\r\n";
    }

    return str;
}

processBatch = function(ast) {
    var identifier, service, serviceName,
        generatedCode, outString, input;

    identifier = ast[0];
    service = ast[1];
    block = ast[2];

    identifier.traverseTopDown(
      'LetDecl(name),', function(b) {
        identifier = b.name.value;
      }
    );
    if( !identifier ) 
      throw "illegal batch statement";

    if( service.cons == "ERROR" ) {
      throw "illegal batch statement";
    }
    serviceName = service[0].value;

    // Input for the batch script
    input = {};

    // Transform ForEeach nodes
    block[0].traverseTopDown('Call(_,_)', function() {
      var node = this;
      
      if( node[0].cons == 'PropAccess' ) {
        node[0].traverseTopDown('PropAccess(subject,"forEach")', function(b) {
          node.cons = 'ForEach';
        });
      }
    });
    
    // Generate code
    var v = new visitor.Visitor(identifier);
    v.reset();
    v.dispatchVisit(block[0]); 

    // Start of batch closure
    outString  = '(function($service$){\n';
    outString += 'var $input$ = '+JSON.stringify(input)+';\n';
    // Body of batch closure
    outString += '\n/* Init code */\n';
    outString += v.getInit();
    outString += '\n/* Remote code */\n';
    outString += 'var $script$ = \'' + v.getRemote() + '\';\n';
    outString += 'var $batch$ = $service$.execute($script$, $input$, function($result$) {\n';
    outString += '\n/* Local code */\n';
    outString += v.getLocal();
    // End of batch closure
    outString += '\n});\n})('+serviceName+')';

    return outString;
}
exports.compile = compile;
exports.getAST = getAST;
